package com.ballmaze.service;

import com.alibaba.fastjson.JSON;
import com.ballmaze.BeanUtil;
import com.ballmaze.conn.websocket.MazeResponse;
import com.ballmaze.maze.MazeAction;
import com.ballmaze.maze.MazeLocation;
import com.ballmaze.maze.MazeManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Component;

import javax.websocket.Session;
import java.io.IOException;
import java.util.HashMap;
import java.util.concurrent.CopyOnWriteArraySet;

@Component
@DependsOn("getMazeManager")
@Slf4j
public class WebSocketService {
    private CopyOnWriteArraySet<Session> playerSessions;
    private Session observerSession;
    private HashMap<String, Integer> userIdTimes;
    private HashMap<Session, Integer> session2Id;
    MazeManager mazeManager;

    public WebSocketService() {
        log.info("【WebSocketService】 initialization...");
        mazeManager = BeanUtil.getBean(MazeManager.class);
        playerSessions = new CopyOnWriteArraySet<>();
        userIdTimes = new HashMap<>();
        session2Id = new HashMap<>();
    }

    public boolean add(Session session, String route, String userid) {
        if (route.equals("p")) {
            Integer idTimes = userIdTimes.getOrDefault(userid, 0);
            if (idTimes == 0) {
                playerSessions.add(session);
                session2Id.put(session, Integer.valueOf(userid));
                userIdTimes.put(userid, 1);
                return true;
            } else {
                userIdTimes.put(userid, idTimes + 1);
                return false;
            }
        } else {
            if (observerSession == null) {
                observerSession = session;
                return true;
            } else {
                return false;
            }
        }
    }

    public boolean remove(Session session, String route, String userid) {
        if (route.equals("p")) {
            Integer idTimes = userIdTimes.getOrDefault(userid, 0);
            if (idTimes == 0) {
                return false;
            } else {
                idTimes--;
                userIdTimes.put(userid, idTimes);
                if (idTimes == 0) {
                    userIdTimes.remove(userid);
                    playerSessions.remove(session);
                    session2Id.remove(session);
                    return true;
                }
                return false;
            }
        } else {
            if (observerSession != null) {
                observerSession = null;
                return true;
            } else {
                return false;
            }
        }
    }

    public Object size() {
        return playerSessions.size();
    }

    public CopyOnWriteArraySet<Session> list() {
        return playerSessions;
    }

    /**
     * 发送消息
     */
    public void sendMessage() {
//        log.info("【广播发送】，信息:{}，总连接数:{}", message, webSocketSessions.size());
        for (Session session : playerSessions) {
            try {
                Integer userId = session2Id.get(session);
                char[][] vision = mazeManager.getMazeDrawer().getGraphData(userId);
                MazeLocation playerLocation = mazeManager.getPlayer(userId).getLocation();
//                MazeLocation[] obstacles = mazeManager.getObstacles();
                float reward = mazeManager.getReward(userId);
                MazeResponse response = new MazeResponse(playerLocation, vision, reward);
                session.getBasicRemote().sendText(JSON.toJSONString(response));
            } catch (IOException e) {
//                log.info("【广播发送】，信息异常:{}", e.fillInStackTrace());
                System.out.println(e);
            }
        }
        if (observerSession != null) {
            try {
                String graphData = mazeManager.getMazeDrawer().toGraphData();
                observerSession.getBasicRemote().sendText(graphData);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 处理 onMessage 的方法
     *
     * @param userid  对方的id
     * @param session 会话本身
     */
    public void onMessage(String userid, Session session, String message) {
        log.info(message);
        MazeAction action = MazeAction.MazeActionBuilder.getInstance().build(userid, message);
        System.out.println(action);
        mazeManager.insertAction(action);
    }
}
